home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1998 / MacHack 1998.toast / The Hacks! / PCA Icon Arranger ƒ / PCoord3.p < prev    next >
Encoding:
Text File  |  1998-06-20  |  12.8 KB  |  538 lines  |  [TEXT/PJMM]

  1. unit PCoord3;
  2. { Modification History }
  3. { March 1998 Think Pascal version by Philippe Casgrain }
  4. { June 1998 made in a unit for MacHack }
  5.  
  6. interface
  7.  
  8.     uses
  9.         Printing, MacInit, Statis, MathDeclarations;
  10.  
  11.     function GetCoords (resemblanceMatrix: TMatrixPtr;
  12.                                     estUneMatriceDistance: boolean;
  13.                                     nombreDimensions: Integer): TMatrixPtr;
  14.  
  15. implementation
  16.  
  17. {    Printing, MacInit, Statis;}
  18.     const
  19.         nbcar = 10;
  20.         MenuCoVAR = 6002;
  21.     type
  22.         VARiint = 1..3;
  23.         VARiable = record
  24.                 case VARiint of
  25.                     1: (
  26.                             int: INTEGER
  27.                     );
  28.                     2: (
  29.                             re: ExtENDed
  30.                     );
  31.                     3: (
  32.                             car: alpha
  33.                     );
  34.             end;
  35.     var
  36.         i, j, k, p, nbdesc: INTEGER;
  37.         ptrmin, ptrmax, compte, nbvalides, nbespaces, nobj, ASauter: INTEGER;
  38.         x1, plusgrand, pluspetit, y, y1, rayoncarre, valmax, MaxPt: ExtENDed;
  39.         distance: BOOLEAN;
  40.         VARi: VARiable;
  41.         entree: FileTYPE;
  42.         GLin, GMult, x, b, c, cs, sn, pp, Diagonale, Ptri: Ptr;
  43.         car: char;
  44.         FichPos, FichVP: FileTYPE;
  45.         ThePtr: PtrTYPE;
  46.         grow, MatDim, Space: Size;
  47.         ShowGeneral: WindowPtr;
  48.         Menu2Hdl: MenuHandle;
  49.  
  50.         resultMatrix: TMatrixPtr;
  51.  
  52.  
  53.     procedure symmetric (n: INTEGER;
  54.                                     g, x, a: Ptr);
  55.         label
  56.             11, 77;
  57.         var
  58.             i, j, k, m, m1: LongInt;
  59.             Ancienm: INTEGER;
  60.             t, norm, eps, sine, cosine, lambda, mu, a0, a1, b0, beta, x0, x1, w1, w2, Temp1, Temp2: ExtENDed;
  61.  
  62.         function max (a, b: ExtENDed): ExtENDed;
  63.         begin
  64.             if a > b then
  65.                 max := a
  66.             else
  67.                 max := b;
  68.         end;
  69.  
  70.         procedure householder (n: INTEGER;
  71.                                         var g, x, a, b: Ptr;
  72.                                         var norm: ExtENDed);
  73.             var
  74.                 i, j, k: LongInt;
  75.                 t, sigma, alpha, beta, gamma, absb, provi, Temp1, Temp2: ExtENDed;
  76.         begin
  77.             norm := 0;
  78.             absb := 0;
  79.             for k := 1 to n - 2 do begin
  80.                 with AdVec(a, k).PtrRee^ do
  81.                     Reel := AdLin(G, k, k).PtrRee^.Reel;
  82.                 sigma := 0;
  83.                 for i := k + 1 to n do
  84.                     with AdLin(g, i, k).PtrRee^ do
  85.                         sigma := sigma + sqr(Reel);
  86.                 with AdVec(a, k).PtrRee^ do
  87.                     t := absb + abs(Reel);
  88.                 absb := sqrt(sigma);
  89.                 norm := max(norm, t + absb);
  90.                 with AdLin(g, k + 1, k).PtrRee^ do
  91.                     alpha := Reel;
  92.                 if alpha < 0 then
  93.                     beta := absb
  94.                 else
  95.                     beta := -absb;
  96.                 with AdVec(b, k).PtrRee^ do
  97.                     Reel := beta;
  98.                 if sigma <> 0 then begin
  99.                     gamma := 1 / (sigma - alpha * beta);
  100.                     with AdLin(G, k + 1, k).PtrRee^ do
  101.                         Reel := alpha - beta;
  102.                     for i := k + 1 to n do begin
  103.                         provi := 0;
  104.                         for j := k + 1 to i do begin
  105.                             with AdLin(GLin, i, j).PtrRee^ do
  106.                                 w1 := Reel;
  107.                             with AdLin(G, j, k).PtrRee^ do
  108.                                 provi := provi + w1 * Reel;
  109.                         end;
  110.                         for j := i + 1 to n do begin
  111.                             with AdLin(G, j, i).PtrRee^ do
  112.                                 w1 := Reel;
  113.                             with AdLin(G, j, k).PtrRee^ do
  114.                                 provi := provi + w1 * Reel;
  115.                         end;
  116.                         with AdVec(pp, i).PtrRee^ do
  117.                             Reel := provi * gamma;
  118.                     end;
  119.                     t := 0;
  120.                     for i := k + 1 to n do begin
  121.                         with AdLin(G, i, k).PtrRee^ do
  122.                             temp1 := Reel;
  123.                         with AdVec(pp, i).PtrRee^ do
  124.                             t := t + temp1 * Reel;
  125.                     end;
  126.                     t := t * 0.5 * gamma;
  127.                     for i := k + 1 to n do begin
  128.                         with AdLin(G, i, k).PtrRee^ do
  129.                             temp1 := Reel;
  130.                         with AdVec(pp, i).PtrRee^ do
  131.                             Reel := Reel - t * temp1;
  132.                     end;
  133.                     for i := k + 1 to n do
  134.                         for j := k + 1 to i do begin
  135.                             with AdLin(G, i, k).PtrRee^ do
  136.                                 w1 := Reel;
  137.                             with AdLin(G, j, k).PtrRee^ do
  138.                                 w2 := Reel;
  139.                             with AdVec(pp, j).PtrRee^ do
  140.                                 Temp1 := Reel;
  141.                             with AdVec(pp, i).PtrRee^ do
  142.                                 Temp2 := Reel;
  143.                             with AdLin(G, i, j).PtrRee^ do
  144.                                 Reel := Reel - w1 * Temp1 - Temp2 * w2;
  145.                         end;
  146.                     for i := 2 to n do begin
  147.                         provi := 0;
  148.                         for j := k + 1 to n do begin
  149.                             with AdLin(G, j, k).PtrRee^ do
  150.                                 W1 := Reel;
  151.                             with AdMat(x, i, j).PtrRee^ do
  152.                                 provi := provi + w1 * Reel;
  153.                         end;
  154.                         with AdVec(pp, i).PtrRee^ do
  155.                             Reel := gamma * provi;
  156.                     end;
  157.                     for i := 2 to n do
  158.                         for j := k + 1 to n do begin
  159.                             with AdLin(G, j, k).PtrRee^ do
  160.                                 w1 := Reel;
  161.                             with AdVec(pp, i).PtrRee^ do
  162.                                 Temp1 := Reel;
  163.                             with AdMat(x, i, j).PtrRee^ do
  164.                                 Reel := Reel - Temp1 * w1;
  165.                         end;
  166.                 end;
  167.             end;
  168.             with AdLin(G, n - 1, n - 1).PtrRee^ do
  169.                 Temp1 := Reel;
  170.             with AdLin(G, n, n).PtrRee^ do
  171.                 Temp2 := Reel;
  172.             with AdLin(G, n, n - 1).PtrRee^ do
  173.                 w1 := Reel;
  174.             with AdVec(a, n - 1).PtrRee^ do
  175.                 Reel := Temp1;
  176.             with AdVec(a, n).PtrRee^ do
  177.                 Reel := Temp2;
  178.             with AdVec(b, n - 1).PtrRee^ do
  179.                 Reel := w1;
  180.             t := abs(w1);
  181.             norm := max(norm, absb + abs(Temp1) + t);
  182.             norm := max(norm, t + abs(Temp2));
  183.         end;        (* fin de householder *)
  184.  
  185.     begin        (* debut de symmetric *)
  186.         for i := 1 to n do begin
  187.             with AdMat(x, i, i).PtrRee^ do
  188.                 Reel := 1;
  189.             for j := i + 1 to n do begin
  190.                 with AdMat(x, i, j).PtrRee^ do
  191.                     Reel := 0;
  192.                 with AdMat(x, j, i).PtrRee^ do
  193.                     Reel := 0;
  194.             end;
  195.         end;
  196.         with AdVec(b, n).PtrRee^ do
  197.             Reel := 0;
  198.         householder(n, g, x, a, b, norm);
  199.         eps := norm * 1.3e-7;
  200.         with AdVec(b, 0).PtrRee^ do
  201.             Reel := 0;
  202.         mu := 0;
  203.         m := n;
  204.         AncienM := 0;
  205. 11:
  206.         if m = 0 then
  207.             goto 77
  208.         else begin
  209.             i := m - 1;
  210.             k := m - 1;
  211.             m1 := m - 1;
  212.         end;
  213.         if AncienM <> m then begin
  214.             AncienM := M;
  215.         end;
  216.         with AdVec(b, k).PtrRee^ do
  217.             w1 := Reel;
  218.         if abs(W1) <= eps then begin
  219.             with AdVec(a, m).PtrRee^ do
  220.                 w1 := Reel;
  221.             with AdLin(G, m, m).PtrRee^ do
  222.                 Reel := w1;
  223.             m := k;
  224.             goto 11;
  225.         end;
  226.         repeat
  227.             i := i - 1;
  228.             with AdVec(b, i).PtrRee^ do
  229.                 w1 := Reel;
  230.         until abs(w1) <= eps;
  231.         k := i + 1;
  232.         with AdVec(b, m1).PtrRee^ do
  233.             b0 := sqr(Reel);
  234.         with AdVec(a, m1).PtrRee^ do
  235.             Temp1 := Reel;
  236.         with AdVec(a, m).PtrRee^ do
  237.             Temp2 := Reel;
  238.         a1 := sqrt(sqr(Temp1 - Temp2) + 4 * b0);
  239.         t := Temp1 * Temp2 - b0;
  240.         a0 := Temp1 + Temp2;
  241.         if a0 >= 0 then
  242.             lambda := a0 + a1
  243.         else
  244.             lambda := a0 - a1;
  245.         t := t / lambda;
  246.         if abs(t - mu) < 0.5 * abs(t) then begin
  247.             mu := t;
  248.             lambda := t;
  249.         end
  250.         else if abs(lambda - mu) < 0.5 * abs(lambda) then
  251.             mu := lambda
  252.         else begin
  253.             mu := t;
  254.             lambda := 0;
  255.         end;
  256.         with AdVec(a, k).PtrRee^ do
  257.             Reel := Reel - lambda;
  258.         with AdVec(b, k).PtrRee^ do
  259.             beta := Reel;
  260.         for j := k to m1 do begin
  261.             with AdVec(a, j).PtrRee^ do
  262.                 a0 := Reel;
  263.             with AdVec(a, j + 1).PtrRee^ do
  264.                 a1 := Reel - lambda;
  265.             with AdVec(b, j).PtrRee^ do
  266.                 b0 := Reel;
  267.             t := sqrt(sqr(a0) + sqr(beta));
  268.             cosine := a0 / t;
  269.             with AdVec(cs, j).PtrRee^ do
  270.                 Reel := cosine;
  271.             sine := beta / t;
  272.             with AdVec(sn, j).PtrRee^ do
  273.                 Reel := sine;
  274.             with AdVec(a, j).PtrRee^ do
  275.                 Reel := cosine * a0 + sine * beta;
  276.             with AdVec(a, j + 1).PtrRee^ do
  277.                 Reel := -sine * b0 + cosine * a1;
  278.             with AdVec(b, j).PtrRee^ do
  279.                 Reel := cosine * b0 + sine * a1;
  280.             with AdVec(b, j + 1).PtrRee^ do
  281.                 beta := Reel;
  282.             with AdVec(b, j + 1).PtrRee^ do
  283.                 Reel := cosine * beta;
  284.             with AdVec(c, j).PtrRee^ do
  285.                 Reel := sine * beta;
  286.         end;
  287.         with AdVec(b, k - 1).PtrRee^ do
  288.             Reel := 0;
  289.         with AdVec(c, k - 1).PtrRee^ do
  290.             Reel := 0;
  291.         for j := k to m1 do begin
  292.             with AdVec(sn, j).PtrRee^ do
  293.                 sine := Reel;
  294.             with AdVec(cs, j).PtrRee^ do
  295.                 cosine := Reel;
  296.             with AdVec(a, j).PtrRee^ do
  297.                 a0 := Reel;
  298.             with AdVec(b, j).PtrRee^ do
  299.                 b0 := Reel;
  300.             with AdVec(c, j - 1).PtrRee^ do
  301.                 w1 := Reel;
  302.             with AdVec(b, j - 1).PtrRee^ do
  303.                 Reel := Reel * cosine + w1 * sine;
  304.             with AdVec(a, j).PtrRee^ do
  305.                 Reel := a0 * cosine + b0 * sine + lambda;
  306.             with AdVec(b, j).PtrRee^ do
  307.                 Reel := -a0 * sine + b0 * cosine;
  308.             with AdVec(a, j + 1).PtrRee^ do
  309.                 Reel := Reel * cosine;
  310.             for i := 1 to n do begin
  311.                 with AdMat(x, i, j + 1).PtrRee^ do
  312.                     x1 := Reel;
  313.                 with AdMat(x, i, j).PtrRee^ do begin
  314.                     x0 := Reel;
  315.                     Reel := x0 * cosine + x1 * sine;
  316.                 end;
  317.                 with AdMat(x, i, j + 1).PtrRee^ do
  318.                     Reel := -x0 * sine + x1 * cosine;
  319.             end;
  320.         end;
  321.         with AdVec(a, m).PtrRee^ do
  322.             Reel := Reel + lambda;
  323.         goto 11;
  324. 77:
  325.     end;  (* Fin Symmetric *)
  326.  
  327.  
  328.     procedure nouvellescoord;
  329.         var
  330.             i, j, k: INTEGER;
  331.  
  332.     begin
  333.         if NewMatrix(resultMatrix, nbDesc, nbEspaces, false, false) then
  334.             for j := 1 to nbdesc do begin
  335.                 for i := 1 to nbespaces do begin
  336.                     with AdVec(Ptri, i).PtrInt^ do
  337.                         k := Int;
  338.                     with AdMat(x, j, k).PtrRee^ do begin
  339.                         SetElement(resultMatrix, j, i, Reel);
  340.                     end;
  341.                 end;
  342.             end;
  343.     end;        (* fin nouvelles coordonnees *)
  344.  
  345.  
  346.  
  347.  
  348.     procedure shell (a, Ptri: Ptr;
  349.                                     n: INTEGER);
  350.         label
  351.             1;
  352.         var
  353.             i, j, k, m, o, i1, i2: INTEGER;
  354.             w, ww: ExtENDed;
  355.     begin
  356.         for i := 1 to n do
  357.             m := 2 * i - 1;
  358.         m := m div 2;
  359.         while m <> 0 do begin
  360.             k := n - m;
  361.             for j := 1 to k do begin
  362.                 i := j;
  363.                 while i >= 1 do begin
  364.                     with AdVec(a, i).PtrRee^ do
  365.                         w := Reel;
  366.                     with AdVec(a, i + m).PtrRee^ do
  367.                         if Reel <= w then
  368.                             goto 1;
  369.                     o := i + m;
  370.                     with AdVec(a, o).PtrRee^ do
  371.                         ww := Reel;
  372.                     with AdVec(a, i).PtrRee^ do
  373.                         Reel := ww;
  374.                     with AdVec(a, o).PtrRee^ do
  375.                         Reel := w;
  376.                     with AdVec(Ptri, o).PtrInt^ do
  377.                         i2 := Int;
  378.                     with AdVec(Ptri, i).PtrInt^ do
  379.                         i1 := Int;
  380.                     with AdVec(Ptri, i).PtrInt^ do
  381.                         Int := i2;
  382.                     with AdVec(Ptri, i).PtrInt^ do
  383.                         Int := i1;
  384.                     i := i - m;
  385.                 end;
  386. 1:
  387.             end;
  388.             m := m div 2;
  389.         end;
  390.     end;    (* fin de shell *)
  391.  
  392.     procedure Normalise;
  393.         var
  394.             i, j, k: INTEGER;
  395.             w: ExtENDed;
  396.     begin
  397.         for j := 1 to nbdesc do begin
  398.             for i := 1 to nbValides do begin
  399.                 with AdVec(Diagonale, i).PtrRee^ do
  400.                     w := Reel;
  401.                 with AdVec(Ptri, i).PtrInt^ do
  402.                     k := Int;
  403.                 with AdMat(x, j, k).PtrRee^ do
  404.                     Reel := Reel * sqrt(w);
  405.             end;
  406.         end;
  407.     end;
  408.  
  409.     procedure CopyVP;
  410.         var
  411.             i: INTEGER;
  412.     begin
  413.         x1 := 0;
  414.         y := 0;
  415.         for i := 1 to nbdesc do
  416.             with AdVec(Diagonale, i).PtrRee^ do
  417.                 x1 := x1 + Reel;
  418.         with AdVec(Diagonale, NbDesc).PtrRee^ do
  419.             if Reel < 0 then begin
  420.                 y := -Reel;
  421.                 x1 := x1 + nbdesc * y;
  422.             end;
  423.     end;
  424.  
  425.  
  426.     procedure EcritEntete (matRessemblance: TMatrixPtr);
  427.         var
  428.             I, J, k: LongInt;
  429.             Mult: Variable;
  430.             x, Total, w, ww: Extended;
  431.  
  432.     begin
  433.         Nbdesc := matRessemblance^.n;
  434.         NobjSimil := NbDesc;
  435.         Space := NbDesc;
  436.         Space := (Space * (Space + 1)) div 2;
  437.         MatDim := (NbDesc + 1) * 3;
  438.         if Space < MatDim then
  439.             Space := MatDim;
  440.         Diagonale := Memoire(1, NbDesc, 1, 1, ReelBytes, True);
  441.         if NbDesc mod 2 = 0 then
  442.             GLin := Memoire(1, NbDesc div 2, 1, NbDesc + 1, ReelBytes, True)
  443.         else
  444.             GLin := Memoire(1, NbDesc, 1, (NbDesc + 1) div 2, ReelBytes, True);
  445.         Nobj := matRessemblance^.n; { pas important }
  446.         NbDescSimil := Nobj;
  447.  
  448.         for i := 1 to nbdesc do
  449.             with AdVec(Diagonale, i).PtrRee^ do
  450.                 Reel := 0;
  451.         total := 0;
  452.         k := 0;
  453.         (* remplissage de la matrice *)
  454.         for i := 1 to nbdesc do begin
  455.             for j := i + 1 to nbdesc do begin
  456.                 Mult.re := GetElement(matRessemblance, i, j);
  457.                 if distance then
  458.                     x := (-sqr(Mult.re) / 2)
  459.                 else
  460.                     x := (-sqr(1 - Mult.re) / 2);
  461.                 with AdLin(GLin, j, i).PtrRee^ do
  462.                     Reel := x;
  463.                 with AdVec(Diagonale, i).PtrRee^ do
  464.                     Reel := Reel + x;
  465.                 with AdVec(Diagonale, j).PtrRee^ do
  466.                     Reel := Reel + x;
  467.                 total := total + x + x;
  468.             end;
  469.             with AdLin(GLin, i, i).PtrRee^ do
  470.                 Reel := 0;
  471.         end;
  472.         for i := 1 to nbdesc do
  473.             with AdVec(Diagonale, i).PtrRee^ do
  474.                 Reel := Reel / nbdesc;
  475.         total := total / nbdesc / nbdesc;
  476.         for i := 1 to nbdesc do begin
  477.             for j := 1 to i do begin
  478.                 with AdVec(Diagonale, i).PtrRee^ do
  479.                     w := Reel;
  480.                 with AdVec(Diagonale, j).PtrRee^ do
  481.                     ww := Reel;
  482.                 with AdLin(GLin, i, j).PtrRee^ do
  483.                     Reel := Reel - w - ww + total;
  484.             end;
  485.         end;
  486.     end;    (* ENTETE *)
  487.  
  488.     function GetCoords (resemblanceMatrix: TMatrixPtr;
  489.                                     estUneMatriceDistance: boolean;
  490.                                     nombreDimensions: Integer): TMatrixPtr;
  491.         var
  492.             fatalError: Boolean;
  493.             i: Integer;
  494.     begin    (* prog princ *)
  495.         fatalError := false;
  496.         resultMatrix := nil;
  497.  
  498.         FichierSimil := TRUE;
  499.         NbFiles := 0;
  500.         Distance := estUneMatriceDistance;
  501. {LisFichSimil(4, entree, TRUE); voila qui ouvre une ref au fichier simil dans entree}
  502.         EcritEntete(resemblanceMatrix);
  503.         x := Memoire(1, NbDesc, 1, NbDesc, ReelBytes, TRUE);
  504.         b := Memoire(0, NbDesc + 1, 1, 1, ReelBytes, TRUE);
  505.         c := Memoire(0, NbDesc + 1, 1, 1, ReelBytes, TRUE);
  506.         cs := Memoire(0, NbDesc + 1, 1, 1, ReelBytes, TRUE);
  507.         sn := Memoire(0, NbDesc + 1, 1, 1, ReelBytes, TRUE);
  508.         pp := Memoire(0, NbDesc + 1, 1, 1, ReelBytes, TRUE);
  509.         symmetric(nbdesc, glin, x, diagonale);
  510.         DisposeMemoire(b);
  511.         DisposeMemoire(c);
  512.         DisposeMemoire(cs);
  513.         DisposeMemoire(sn);
  514.         DisposeMemoire(pp);
  515.         GMult := Memoire(1, NbDesc + 2, 1, 3, ReelBytes, TRUE);
  516.         Ptri := Memoire(1, NbDesc, 1, 1, IntBytes, TRUE);
  517.         for i := 1 to nbdesc do
  518.             with AdVec(Ptri, i).PtrInt^ do
  519.                 Int := i;
  520.         shell(diagonale, Ptri, nbdesc);
  521.         nbvalides := 0;
  522.         while (AdVec(Diagonale, nbvalides + 1).PtrRee^.Reel > epsilon) and (nbvalides < nbdesc) do
  523.             nbvalides := nbvalides + 1;
  524.         Normalise;
  525.         CopyVP;
  526.         if nbvalides <= 1 then
  527.             fatalError := true;
  528.         if not fatalError then begin
  529.             nbespaces := nombreDimensions;
  530.             if NbEspaces > 0 then begin
  531.                 NouvellesCoord;
  532.             end;
  533.         end; { if not fataError }
  534.  
  535.         GetCoords := resultMatrix;
  536.     end; { GetCoordinates }
  537.  
  538. end. { unit }